package com.snow.common.config;


import com.snow.common.annotation.Nfs;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.errors.InvalidEndpointException;
import io.minio.errors.InvalidPortException;
import io.minio.messages.Bucket;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Component
@Slf4j
@Data
@Configuration
@EnableConfigurationProperties({MinioConfig.class})
@ConditionalOnClass({MinioClient.class})
@ConditionalOnProperty(name = "minio.enable", havingValue = "true")
@ComponentScan(
        basePackages = "com.snow.common.controller"
        , useDefaultFilters = false
        , includeFilters = {@ComponentScan.Filter(classes = {Nfs.class}
)})
public class MinioUtils implements InitializingBean {

    private final static String BUCKETNAME = "yanke";
    private final static String CONTENTTYPE = "image/jpeg";

    private MinioConfig minioConfig;
    private MinioClient instance;

    public MinioUtils(MinioConfig minioConfig) {
        this.minioConfig = minioConfig;
    }

    //    @PostConstruct
    /*public void init() {
        try {
            instance = new MinioClient(minioConfig.getEndpoint(), minioConfig.getAccessKey(), minioConfig.getSecretKey());
            log.info(">>>>>>>>>>>>>>>>>>>>Minio连接成功,url:{}<<<<<<<<<<<<<<<<<<<", minioConfig.getEndpoint());
        } catch (InvalidEndpointException e) {
            e.printStackTrace();
        } catch (InvalidPortException e) {
            e.printStackTrace();
        }
    }*/

    /**
     * 上传文件
     */
    public void uploadFile(String bucketname, InputStream in) {
        bucketname = Optional.ofNullable(bucketname).orElseGet(() -> BUCKETNAME);
        try {
            String fileName = RandomStringUtils.random(10, true, true);
            fileName = fileName + ".jpg";
            PutObjectOptions options = new PutObjectOptions(in.available(), -1L);
            options.setContentType(CONTENTTYPE);
            instance.putObject(bucketname, fileName, in, options);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     */
    public void uploadFile(String bucketname, InputStream in, String fileName, String contentType) {
        bucketname = Optional.ofNullable(bucketname).orElseGet(() -> BUCKETNAME);
        try {
            fileName = Optional.ofNullable(fileName).orElseGet(() -> {
                String name = RandomStringUtils.random(10, true, true);
                return name = name + ".jpg";
            });

            PutObjectOptions options = new PutObjectOptions(in.available(), -1L);
            Optional.ofNullable(contentType).ifPresent(v -> {
                options.setContentType(contentType);
            });
            instance.putObject(bucketname, fileName, in, options);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     */
    public void uploadFile(String bucketname, String filePath) {
        bucketname = Optional.ofNullable(bucketname).orElseGet(() -> BUCKETNAME);
        try {
            String fileName = RandomStringUtils.random(10, true, true);
            fileName = fileName + ".jpg";
            instance.putObject(bucketname, fileName, filePath, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 是否存在对象
     */
    public Boolean isExistObject(String bucketname, String object) {
        bucketname = Optional.ofNullable(bucketname).orElseGet(() -> BUCKETNAME);
        try {
            ObjectStat objectStat = instance.statObject(bucketname, object);
            return Optional.ofNullable(objectStat).isPresent();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取外链
     */
    public String presignedGetObject(String bucketname, String object) {
        String presignedGetObject = null;
        bucketname = Optional.ofNullable(bucketname).orElseGet(() -> BUCKETNAME);
        try {
            presignedGetObject = instance.presignedGetObject(bucketname, object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Optional.ofNullable(presignedGetObject).<RuntimeException>orElseThrow(() -> {
            throw new RuntimeException();
        });
        return presignedGetObject;
    }

    /**
     * 获取外链,有效期
     */
    public String presignedGetObject(String bucketname, String object, int expire) {
        String presignedGetObject = null;
        bucketname = Optional.ofNullable(bucketname).orElseGet(() -> BUCKETNAME);
        try {
            presignedGetObject = instance.presignedGetObject(bucketname, object, expire);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Optional.ofNullable(presignedGetObject).<RuntimeException>orElseThrow(() -> {
            throw new RuntimeException();
        });
        return presignedGetObject;
    }

    @Override
    public void afterPropertiesSet() {
        if (Objects.isNull(minioConfig.getEndpoint())) {
            return;
        }
        try {
            instance = new MinioClient(minioConfig.getEndpoint(), minioConfig.getAccessKey(), minioConfig.getSecretKey());
            try {
                List<Bucket> buckets = instance.listBuckets();
                if (buckets.isEmpty()) {
                    log.warn("Minio连接不成功");
                } else {
                    log.info(">>>>>>>>>>>>>>>>>>>>Minio连接成功,url:{}<<<<<<<<<<<<<<<<<<<", minioConfig.getEndpoint());
                }
            } catch (Exception e) {
                log.warn("Minio连接不成功");
            }
        } catch (InvalidEndpointException e) {
            e.printStackTrace();
        } catch (InvalidPortException e) {
            e.printStackTrace();
        }
    }
}
